//
// Created on 2025/7/21.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef STREAMCORE_STREAM_H
#define STREAMCORE_STREAM_H

#include <cstddef>
#include <mutex>
#include <stdexcept>
#include <string>

namespace StreamError {
static constexpr const char *ERR_CLOSED = "Stream operation on closed stream";
static constexpr const char *ERR_INVALID_OFFSET = "Buffer offset out of range";
static constexpr const char *ERR_INVALID_BUFFER = "Invalid buffer";
static constexpr const char *ERR_INVALID_COUNT = "Invalid byte count";
static constexpr const char *ERR_INVALID_SEEK_ORIGIN = "Invalid seek origin";
static constexpr const char *ERR_ABORTED = "Stream operation aborted";

[[noreturn]] static void ThrowClosed() { throw std::runtime_error(ERR_CLOSED); }

[[noreturn]] static void ThrowInvalidOffset() { throw std::runtime_error(ERR_INVALID_OFFSET); }

[[noreturn]] static void ThrowInvalidBuffer() { throw std::runtime_error(ERR_INVALID_BUFFER); }

[[noreturn]] static void ThrowInvalidCount() { throw std::runtime_error(ERR_INVALID_COUNT); }

[[noreturn]] static void ThrowInvalidSeekOrigin() { throw std::runtime_error(ERR_INVALID_SEEK_ORIGIN); }

[[noreturn]] static void ThrowAborted() { throw std::runtime_error(ERR_ABORTED); }

[[noreturn]] static void ThrowNotSupported(const char *method_name) {
    throw std::runtime_error(std::string(method_name) + " method not supported.");
}

[[noreturn]] static void ThrowNotSupported_UnseekableStream() {
    throw std::runtime_error("The stream does not support seek operations");
}
[[noreturn]] static void ThrowNotSupported_UnwritableStream() {
    throw std::runtime_error("The stream does not support write operations");
}
[[noreturn]] static void ThrowNotSupported_UnreadableStream() {
    throw std::runtime_error("The stream does not support read operations");
}

// 带格式化消息的版本（可选）
template <typename... Args> [[noreturn]] static void ThrowWithFormat(const char *format, Args... args) {
    char buffer[512];
    snprintf(buffer, sizeof(buffer), format, args...);
    throw std::runtime_error(buffer);
}
} // namespace StreamError


// ==================================================
//                    Stream 基类
// ==================================================
class Stream {
public:
    enum class SeekOrigin { Begin, Current, End };

    Stream() {}
    virtual ~Stream() { close(); }

    // 删除拷贝和移动构造/赋值（如果需要共享所有权，请使用 shared_ptr）
    Stream(const Stream &) = delete;
    Stream &operator=(const Stream &) = delete;

    // ========== 能力查询 (Capabilities) ==========
    virtual bool canRead() const noexcept { return false; }
    virtual bool canWrite() const noexcept { return false; }
    virtual bool canSeek() const noexcept { return false; }

    // ========== 状态查询 ==========
    virtual bool isClosed() const noexcept { return closed_.load(std::memory_order_acquire); }

    // ========== 属性访问 ==========
    virtual size_t position() const { StreamError::ThrowNotSupported("position"); }
    virtual size_t length() const { StreamError::ThrowNotSupported("get length"); }
    virtual void setLength(size_t length) { StreamError::ThrowNotSupported("set length"); }

    // ========== I/O 操作 ==========
    virtual long read(void *buf, long offset, size_t len) { StreamError::ThrowNotSupported("read"); }
    virtual void write(const void *buf, long offset, size_t len) { StreamError::ThrowNotSupported("write"); }
    virtual size_t seek(long offset, SeekOrigin origin) { StreamError::ThrowNotSupported("seek"); }
    virtual void flush() { StreamError::ThrowNotSupported("flush"); }
    virtual void close() {
        bool except = false;
        if (closed_.compare_exchange_weak(except, true)) {
            onClose();
        }
    }

    void copyTo(std::shared_ptr<Stream> stream, size_t bufsize = -1) {
        copyTo(stream.get(), bufsize == -1 ? GetCopyBufferSize() : bufsize);
    }

    virtual void copyTo(Stream *stream, size_t bufsize) {
        if (!canRead())
            throw std::runtime_error("stream not readable.");
        if (!stream->canWrite())
            throw std::runtime_error("stream not writeable.");
        std::vector<uint8_t> temp(bufsize);
        long readByte = 0;
        while (true) {
            readByte = read(temp.data(), 0, temp.size());
            if (readByte <= 0)
                break;

            stream->write(temp.data(), 0, static_cast<size_t>(readByte));
        }
    }

protected:
    virtual void onClose() {}


private:
    std::atomic<bool> closed_{false};

    int32_t GetCopyBufferSize() {
        const long DefaultCopyBufferSize = 81920;
        long bufferSize = DefaultCopyBufferSize;

        if (canSeek()) {
            long len = length();
            long pos = position();
            if (len <= pos) {
                bufferSize = 1;
            } else {
                long remaining = len - pos;
                if (remaining > 0) {
                    bufferSize = std::min<int>(bufferSize, remaining);
                }
            }
        }
        return bufferSize;
    }
};

#endif // STREAMCORE_STREAM_H
